Crate imxrt_rt

source ·
Expand description

Runtime and startup support for i.MX RT processors.

This crate builds on cortex-m-rt and adds support for i.MX RT processors. Using this runtime crate, you can specify FlexRAM sizes and section allocations, then use it to boot your i.MX RT processor.

The crate achieves this with

  • a build-time API to define the memory map.
  • a runtime library to configure the embedded processor.

Both APIs are exposed from the same package. The interface changes depending on the build environment.

§Getting started

Make sure you’re familiar with cortex-m-rt features. This crate re-exports the cortex-m-rt interface. Use this interface to implement your program’s entrypoint, register exceptions, and interrupts. You should be familiar with specifing a linker script for your embedded project.

§Dependencies

In your embedded target, depend on imxrt-rt in both of

  • the [dependencies] section of your Cargo.toml
  • the [build-dependencies] section of your Cargo.toml

Use the same crate version in both locations. If you enable features, you must enable features in both locations. See the features section for more information.

[dependencies.imxrt-rt]
version = # $VERSION

[build-dependencies.imxrt-rt]
version = # Same as $VERSION

§Linker script

Link against imxrt-link.x, which is automatically made available on the linker search path. Do not link against link.x from cortex-m-rt.

You may change the name of the linker script by using the RuntimeBuilder.

§Host configuration

In your project, create a build.rs script that configures the runtime. The simplest build.rs looks like this:

use imxrt_rt::{Family, RuntimeBuilder};

/// CHANGE ME depending on your board's flash size.
const FLASH_SIZE: usize = 16 * 1024 * 1024; // 16 MiB.
/// CHANGE ME depending on your board's chip.
const FAMILY: Family = Family::Imxrt1060;

fn main() {
    RuntimeBuilder::from_flexspi(FAMILY, FLASH_SIZE)
        .build()
        .unwrap();
}

This script works for any i.MX RT 1060-based system that has 16 MiB of external flash. Change the flash size and chip family based on your hardware. It uses the default configuration, which tries to give a reasonable memory layout for all processors. To understand the default configuration, see the RuntimeBuilder documentation.

A more advanced runtime configuration looks like this:

use imxrt_rt::{FlexRamBanks, Memory};

fn main() {
    RuntimeBuilder::from_flexspi(FAMILY, FLASH_SIZE)
        .flexram_banks(FlexRamBanks {
            ocram: 0,
            dtcm: FAMILY.flexram_bank_count() / 2 + 2,
            itcm: FAMILY.flexram_bank_count() / 2 - 2,
        })
        .text(Memory::Itcm)
        .vectors(Memory::Itcm)
        .rodata(Memory::Dtcm)
        .data(Memory::Dtcm)
        .bss(Memory::Dtcm)
        .uninit(Memory::Dtcm)
        .stack(Memory::Dtcm)
        .stack_size(4 * 1024)
        .heap(Memory::Dtcm)
        .heap_size(512)
        .build()
        .unwrap();
}

This configuration maximizes the TCM allocation by removing OCRAM blocks. It takes two banks from ITCM, and gives them to DTCM. It ensures that all sections are allocated to DTCM instead of OCRAM. It reduces the stack size, and reserves space for a small heap.

No matter the configuration, the runtime ensures that all contents are copied from flash into their respective locations before main() is called.

§Target integration

If your runtime uses flash, link against a FlexSPI configuration block (FCB) crate. The crate is expected to export a static FLEXSPI_CONFIGURATION_BLOCK that describes how the FlexSPI peripheral interacts with your external flash chip. If an FCB crate doesn’t exist for your hardware, you can use the imxrt-boot-gen crate to define one. See the teensy4-fcb crate for an example of an FCB crate that is compatible with this runtime.

Finally, use imxrt-rt in your firmware just as you would use cortex-m-rt. See the cortex-m-rt documentation for examples.

§Feature flags

imxrt-rt supports the features available in cortex-m-rt version 0.7.2. If you enable a feature, you must enable it in both the [dependencies] and [build-dependencies] section of your package manifest. For example, if the cortex-m-rt "device" feature were needed, then enable this crate’s "device" feature in both places.

[dependencies.imxrt-rt]
version = # $VERSION
features = ["device"]  # Add the feature here...

[build-dependencies.imxrt-rt]
version = # Same as $VERSION
features = ["device"] # ... and here

§Limitations

The crate considers the assignment of FlexRAM memory banks to ITCM/DTCM/OCRAM an implementation detail. Additionally, the implementation does not care about the assignment of memory bank power domains. This seems to matter most on the 1050, which has the widest spread of bank-to-power domain assignment (according to AN12077).

There is no support for ECC on 1170. The runtime assumes that OCRAM and TCM ECC is disabled, and that the corresponding memory banks can be used for OCRAM.

The runtime installs a cortex-m-rt pre_init function to configure the runtime. You cannot also define a pre_init function, and this crate does not support any other mechanism for running code before main().

The implementation assumes all flash is FlexSPI.

Structs§

Enums§

  • i.MX RT chip family.
  • The FlexSPI peripheral that interfaces your flash chip.
  • Memory partitions.